package com.wuhuahe.luanfeng.netty.example.rpc;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created By wuhuahe
 * author:游龙
 * Date: 2018-07-14
 * Time: 15:52
 * Desc:
 */
public class RpcServer extends Thread {

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext();

        new RpcServer().start();
    }

    private static final Logger logger = LoggerFactory.getLogger(RpcServer.class);
    private static boolean start = false;

    private static final RpcServer server = new RpcServer();
    private RpcServer(){

    }

    public static void startUp(){
        if(start){
            logger.error("Server already startUp.");
            return;
        }
        server.start();
    }

    private static void bind(int port){
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new MyChannelInitializer());
            ChannelFuture future = bootstrap.bind(port).sync();
            logger.info("Server started on port: " + port);
            start = true;
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void shutDown(){
        start = false;
    }

    /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see #start()
     * @see #stop()
     */
    @Override
    public void run() {
        int port = 8080;
        bind(port);
    }
}
